// ============================== 导入依赖 ============================== //

import CORE from '@/CORE'
import mixPath from '../mixPath'
import mixForm from '../form/mixForm'

// ============================== 导出混合 ============================== //

export default {
  /**
   * 混入列表 (配置选项合并)
   */
  mixins: [mixPath],

  /**
   * 属性注册 (抽取以便查阅)
   */
  props: CORE.WEB.ParamCommon,

  /**
   * 状态数据 (函数返回对象)
   */
  data() {
    return mixForm.data()
  },

  /**
   * 计算属性 (慎用箭头函数)
   */
  computed: {
    /**
     * 父级的 Web 组件
     */
    parentWeb() {
      return CORE.componentParent(this, 'WebSearch') || { $props: {}, toSearch: () => ({}) }
    },

    /**
     * 模块路径
     */
    path() {
      const { parentWeb } = this
      return parentWeb.$props.path || ''
    },

    /**
     * 所属对象
     */
    obj() {
      const { param, state } = this
      if (param) return param

      const { parentWeb } = this
      return parentWeb.$props.param || state.param
    },

    /**
     * 是否自动查询
     */
    isAuto() {
      const { parentWeb, autoSearch } = this
      return parentWeb.$props.noAuto ? false : autoSearch
    },

    /**
     * 绑定列表
     */
    bindList: mixForm.computed.bindList,

    /**
     * 数据列表
     */
    valueList: mixForm.computed.valueList,

    /**
     * 是否为多个绑定
     */
    isMulti: mixForm.computed.isMulti,

    /**
     * 属性名称
     */
    prop: mixForm.computed.prop,

    /**
     * 尺寸
     */
    size: mixForm.computed.size,

    /**
     * 布局
     */
    flex() {
      if (this.flex0) return 'flex0'

      // flex16 到 flex1
      const array16 = Array(16).fill()
      for (const i of array16.map((_, i) => 16 - i)) {
        if (this[`flex${i}`]) return `flex${i}`
      }
      return 'flex2'
    },

    /**
     * 参数属性
     */
    paramProps() {
      const { flex, narrow, hasLabel, noLabel } = this
      const narrowStr = narrow ? ' CoreWeb-SearchParam-narrow' : ''
      const flexStr = narrow ? ` flex${flex.slice(4) / 2 | 0}` : ` ${flex}`
      const labelStr = hasLabel ? ' CoreWeb-SearchParam-has-label' : noLabel ? ' CoreWeb-SearchParam-no-label' : ''
      return {
        key: this.$options.name,
        class: `CoreWeb-SearchParam${flexStr}${narrowStr}${labelStr}`,
      }
    },

    /**
     * 标签属性
     */
    labelProps() {
      const { labelWidth, parentWeb, getSize } = this
      const width = labelWidth || parentWeb.labelWidth
      const style = {}
      if (width) style.width = getSize(width)
      return CORE.isEmpty(style) ? null : { style }
    },

    /**
     * 是否已禁用
     */
    isDisabled() {
      const { parentWeb, disabled } = this
      return parentWeb.isDisabled || disabled
    },

    /**
     * 占位提示
     */
    placeholder() {
      const { isDisabled, noTip, tip, hasPre, TIP_PRE, label } = this
      if (isDisabled || noTip) return ''
      return tip || `${hasPre ? TIP_PRE : ''}${label}`
    },

    /**
     * 公共属性
     */
    commonProps() {
      const { elProps, className, isDisabled, noClear, placeholder, size } = this
      return {
        ...elProps,
        class: className,
        disabled: isDisabled,
        clearable: !noClear,
        placeholder,
        size,
      }
    },
  },

  /**
   * 监听属性 (深度 deep 首次 immediate)
   */
  watch: mixForm.watch,

  /**
   * 创建完成 (先抽取再调用)
   */
  created: mixForm.created,

  /**
   * 本地方法 (轻量重要在前)
   */
  methods: {
    /**
     * 是否不等 (可覆盖)
     */
    isDiff() {
      const { obj, prop, model } = this
      const value = obj[prop]

      // 判断是否有值
      if (CORE.isNumber(value) || value) return obj[prop] !== model
      else return model
    },

    /**
     * 设置内部绑定值 (可覆盖)
     */
    setModel() {
      const { obj, prop, EMPTY } = this
      const value = obj[prop]
      this.model = CORE.isNumber(value) ? value : (value || EMPTY)
    },

    /**
     * 获取最终回传值 (可覆盖)
     */
    getValue() {
      const { model } = this
      return model
    },

    /**
     * 是否相等 (可覆盖)
     */
    equals(value) {
      const { obj, prop, init, emitChange } = this

      // 数值类型，直接比较
      if (CORE.isNumber(value)) return obj[prop] === value

      // 无值，但有默认值
      if (!value && init) {
        this.model = init // 设为默认值
        emitChange() // 重新走提交流程
        return true // 本次不再更新
      }

      // 有值，直接比较
      return obj[prop] === value
    },

    /**
     * 提交改变 (可覆盖)
     */
    emitChange() {
      const { getValue, equals, obj, prop, afterEmit } = this

      // 获取新值
      const value = getValue()

      // 判断改变
      if (equals(value)) return

      // 更新绑定
      this.$set(obj, prop, value)
      this.$emit('change', value)

      // 提交之后
      afterEmit()
    },

    /**
     * 提交之后 (可覆盖)
     */
    afterEmit() {
      const { isAuto, parentWeb } = this
      if (isAuto) parentWeb.toSearch()
    },
  },
}
